package com.jiangnan.repository

import com.jiangnan.api.client.DeepSeekApiServiceClient
import com.jiangnan.entity.ChatRequest
import com.jiangnan.entity.ChatStreamResponse
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import okhttp3.ResponseBody
import okio.BufferedSource
import java.io.IOException

class DeepSeekRepository {

    private val api = DeepSeekApiServiceClient.api
    private val gson = Gson()

    /**
     * 发起流式聊天请求，并逐行读取、解析 SSE 格式的增量数据。
     * 将每个增量 content 通过 Flow emit 出去，以便上层可以边读边展示。
     */
    fun streamChatResponse(request: ChatRequest): Flow<String> = flow {
        // 1. 调用接口
        val response = api.getChatStream(request)
        if (!response.isSuccessful) {
            throw IOException("网络请求错误：${response.code()} ${response.message()}")
        }

        // 2. 确保响应体不为空
        val body: ResponseBody = response.body()
            ?: throw IOException("响应体为空")

        // 3. 按行读取并处理 SSE 格式的数据
        body.source().use { source: BufferedSource ->
            while (!source.exhausted()) {
                val line = source.readUtf8Line() ?: continue
                if (line.startsWith("data: ")) {
                    val jsonPart = line.removePrefix("data: ").trim()
                    if (jsonPart == "[DONE]") {
                        break
                    }
                    try {
                        val streamResponse = gson.fromJson(jsonPart, ChatStreamResponse::class.java)
                        val delta = streamResponse.choices
                            ?.firstOrNull()
                            ?.delta
                            ?.content
                        if (!delta.isNullOrEmpty()) {
                            emit(delta)
                        }
                    } catch (e: Exception) {
                        // 解析异常时记录日志或上报，但不要终止整个流
                        e.printStackTrace()
                    }
                }
            }
        }
    }
        // 4. 把整个读取和解析过程放到 IO 线程，避免阻塞主线程
        .flowOn(Dispatchers.IO)
}
